package com.zyl.familyspacecommoncore.utils.ip;
/*
 * Project: Sunyard
 *
 * File Created at 2023/5/23
 *
 * Copyright 2016 Corporation Limited. All rights reserved.
 *
 * This software is the confidential and proprietary information of Company. ("Confidential Information"). You shall not
 * disclose such Confidential Information and shall use it only in accordance with the terms of the license.
 */

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.ServerHttpRequest;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.Query;
import javax.servlet.http.HttpServletRequest;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;

/**
 * @author Leo
 * @Desc
 * @date 2023/5/23 15:30
 */
@Slf4j
public class IpUtils {

    /**
     * localAddresses 减少运行耗时，初始化时吧本机地址缓存起来 缺点，网络改变时，需要重启
     */
    private static List<String> localAddresses = new ArrayList<>();
    static {
        try {
            Enumeration<NetworkInterface> enumNi = NetworkInterface.getNetworkInterfaces();
            while (enumNi.hasMoreElements()) {
                NetworkInterface ifc = enumNi.nextElement();
                if (ifc.isUp()) {
                    Enumeration<InetAddress> enumAdds = ifc.getInetAddresses();
                    while (enumAdds.hasMoreElements()) {
                        InetAddress addr = enumAdds.nextElement();
                        localAddresses.add(addr.getHostAddress());
                    }
                }
            }
            localAddresses.add("localhost");
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * 判断是否同一个地址，无论是主机名还是ip地址
     *
     * @param host1 地址1
     * @param host2 地址2
     * @return Result
     */
    public static boolean sameAddress(String host1, String host2) {
        if (StrUtil.isBlank(host1) || StrUtil.isBlank(host2)) {
            return false;
        }
        try {
            if (isLocal(host1)) {
                host1 = InetAddress.getLocalHost().getHostName();
            }
            if (isLocal(host2)) {
                host2 = InetAddress.getLocalHost().getHostName();
            }
            InetAddress addr1 = InetAddress.getByName(host1);
            InetAddress addr2 = InetAddress.getByName(host2);
            return addr1.getHostAddress().equals(addr2.getHostAddress());
        } catch (UnknownHostException e) {
            log.error(e.getMessage(), e);
            return false;
        }
    }

    public static boolean isLocal(String host) {
        return localAddresses.contains(host);
    }

    /***
     * 获取客户端ip地址(可以穿透代理)
     *
     * @param request 请求头
     * @return Result
     */
    public static String getClientIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (!isValidIp(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeader("HTTP_X_CLUSTER_CLIENT_IP");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeader("HTTP_FORWARDED_FOR");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeader("HTTP_FORWARDED");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeader("HTTP_VIA");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeader("REMOTE_ADDR");
        }
        if (!isValidIp(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 获取客户端ip
     * @param request 请求头
     * @return Result
     */
    public static String getClientIpAddr(ServerHttpRequest request) {
        String ip = request.getHeaders().getFirst("X-Forwarded-For");
        if (!isValidIp(ip)) {
            ip = request.getHeaders().getFirst("Proxy-Client-IP");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeaders().getFirst("WL-Proxy-Client-IP");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeaders().getFirst("HTTP_X_FORWARDED_FOR");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeaders().getFirst("HTTP_X_FORWARDED");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeaders().getFirst("HTTP_X_CLUSTER_CLIENT_IP");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeaders().getFirst("HTTP_CLIENT_IP");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeaders().getFirst("HTTP_FORWARDED_FOR");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeaders().getFirst("HTTP_FORWARDED");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeaders().getFirst("HTTP_VIA");
        }
        if (!isValidIp(ip)) {
            ip = request.getHeaders().getFirst("REMOTE_ADDR");
        }
        if (!isValidIp(ip)) {
            ip = request.getRemoteAddress().getHostName();
        }
        return ip;
    }

    /**
     * 判断ip是否为空
     * @param ip ip地址
     * @return boo
     */
    private static boolean isValidIp(String ip) {
        return !(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip));
    }

    /**
     * 获取tomcat内置服务监听端口
     *
     * @return Result
     */
    public static int getTomcatPort() {
        try {
            MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
            Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"),
                Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
            String port = objectNames.iterator().next().getKeyProperty("port");
            return Integer.parseInt(port);
        } catch (Exception e) {
            log.error("get tomcat port fail", e);
        }
        return 0;
    }

}
/**
 * Revision history ------------------------------------------------------------------------- Date Author Note
 * ------------------------------------------------------------------------- 2023/5/23 Leo creat
 */
